package p.ithorns.framework.common.thread;

import com.alibaba.ttl.threadpool.TtlExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.util.StringUtils;

import java.util.concurrent.*;

/**
 * ThreadPoolFactory
 * 自定义线程工厂
 *
 * @author ithorns
 * @version 1.0
 * @date 2019/7/29 10:56
 */
public class ThreadPoolFactory {

    public final static Thread.UncaughtExceptionHandler EXCEPTION_HANDLER = new ThreadUncaughtExceptionHandler();

    /**
     * 核心线程数
     */
    public final static int SYSTEM_CORE_SIZE = Runtime.getRuntime().availableProcessors();

    /**
     * 创建守护线程池
     */
    public static ExecutorService createDaemonPool(String poolName) {
        return new ThreadPoolExecutor(1, 1,
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(1),
                threadFactory(poolName, true)
        );
    }

    /**
     * 创建单线程池
     * 需指定任务队列大小
     */
    public static ExecutorService createSinglePool(String poolName, int queueSize) {
        return create(1, 1, new LinkedBlockingDeque<>(Math.max(1, queueSize)), poolName);
    }

    /**
     * 创建单线程池
     * 需自定义指定线程队列
     */
    public static ExecutorService createSinglePool(String poolName, BlockingQueue<Runnable> queue) {
        return create(1, 1, queue, poolName);
    }

    public static ExecutorService createDefaultPool(String threadName) {
        return create(
                SYSTEM_CORE_SIZE,
                SYSTEM_CORE_SIZE + 1,
                null,
                threadName,
                null
        );
    }


    public static ExecutorService create(int coreSize, int maxSize, String threadName) {
        return create(coreSize, maxSize, null, threadName, new ThreadPoolExecutor.AbortPolicy());
    }

    public static ExecutorService create(int coreSize, int maxSize, BlockingQueue<Runnable> queue, String threadName) {
        return create(coreSize, maxSize, queue, threadName, new ThreadPoolExecutor.AbortPolicy());
    }

    public static ExecutorService create(int coreSize, int maxSize, BlockingQueue<Runnable> queue, String threadName, RejectedExecutionHandler handler) {
        if (!StringUtils.hasText(threadName)) {
            threadName = "default-executor";
        }

        // 使用Netty的ThreadFactory
        //DefaultThreadFactory threadFactory = new DefaultThreadFactory(threadName);

        if (queue == null) {
            queue = new SynchronousQueue<>(false);
        }

        if (null == handler) {
            handler = new ThreadPoolExecutor.CallerRunsPolicy();
        }

        /*
         * corePoolSize : 线程池中常驻的线程数量。核心线程数，默认情况下核心线程会一直存活，即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
         * maximumPoolSize : 线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时，这个值无效。
         * keepAliveTime : 当线程数量多于 corePoolSize 时，空闲线程的存活时长，超过这个时间就会被回收
         * unit : keepAliveTime 的时间单位
         * workQueue : 存放待处理任务的队列，该队列只接收 Runnable 接口
         * threadFactory : 线程创建工厂
         * handler : 当线程池中的资源已经全部耗尽，添加新线程被拒绝时，会调用RejectedExecutionHandler的rejectedExecution方法，参考 ThreadPoolExecutor 类中的内部策略类
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                coreSize, maxSize,
                60_000L,
                TimeUnit.MILLISECONDS,
                queue,
                threadFactory(threadName, false),
                handler
        );

        //ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();

        threadPoolExecutor.allowCoreThreadTimeOut(true);

        return TtlExecutors.getTtlExecutorService(threadPoolExecutor);
    }

    /**
     * 可调度线程池
     *
     * @param corePoolSize -
     * @return ScheduledExecutorService
     */
    public static ScheduledExecutorService createScheduledPool(int corePoolSize) {
        return createScheduledPool(corePoolSize, "default-scheduler");
    }


    public static ScheduledExecutorService createScheduledPool(int corePoolSize, String name) {
        return createScheduledPool(corePoolSize, name, null);
    }

    /**
     * 可调度线程池
     *
     * @param corePoolSize  -
     * @param threadFactory -
     * @return ScheduledExecutorService
     */
    public static ScheduledExecutorService createScheduledPool(int corePoolSize, String name, ThreadFactory threadFactory) {
        if (threadFactory == null) {
            threadFactory = threadFactory(name, false);
        }
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

    /**
     * 创建线程工厂
     *
     * @param threadName -
     * @return -
     */
    public static ThreadFactory threadFactory(String threadName, boolean daemon) {
        return new ThreadFactoryBuilder()
                .setUncaughtExceptionHandler(EXCEPTION_HANDLER)
                .setDaemon(daemon)
                .setNameFormat(threadName + "-%d")
                .build();
    }

}
